home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tcl8.0 / win / tclWin32Dll.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  8.3 KB  |  363 lines  |  [TEXT/CWIE]

  1. /* 
  2.  * tclWin32Dll.c --
  3.  *
  4.  *    This file contains the DLL entry point which sets up the 32-to-16-bit
  5.  *    thunking code for SynchSpawn if the library is running under Win32s.
  6.  *
  7.  * Copyright (c) 1995-1996 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * SCCS: @(#) tclWin32Dll.c 1.21 97/08/05 11:47:10
  13.  */
  14.  
  15. #include "tclWinInt.h"
  16.  
  17. typedef DWORD (WINAPI * UT32PROC)(LPVOID lpBuff, DWORD dwUserDefined,
  18.     LPVOID *lpTranslationList);
  19.  
  20. typedef BOOL (WINAPI * PUTREGISTER)(HANDLE hModule, LPCSTR SixteenBitDLL,
  21.     LPCSTR InitName, LPCSTR ProcName, UT32PROC* ThirtyTwoBitThunk,
  22.     FARPROC UT32Callback, LPVOID Buff);
  23.  
  24. typedef VOID (WINAPI * PUTUNREGISTER)(HANDLE hModule);
  25.  
  26. static PUTUNREGISTER UTUnRegister = NULL;
  27. static int           tclProcessesAttached = 0;
  28.  
  29. /*
  30.  * The following data structure is used to keep track of all of the DLL's
  31.  * opened by Tcl so that they can be freed with the Tcl.dll is unloaded.
  32.  */
  33.  
  34. typedef struct LibraryList {
  35.     HINSTANCE handle;
  36.     struct LibraryList *nextPtr;
  37. } LibraryList;
  38.  
  39. static LibraryList *libraryList = NULL;    /* List of currently loaded DLL's.  */
  40.  
  41. static HINSTANCE tclInstance;    /* Global library instance handle. */
  42. static int tclPlatformId;    /* Running under NT, 95, or Win32s? */
  43.  
  44. /*
  45.  * Declarations for functions that are only used in this file.
  46.  */
  47.  
  48. static void         UnloadLibraries _ANSI_ARGS_((void));
  49.  
  50. /*
  51.  * The following declaration is for the VC++ DLL entry point.
  52.  */
  53.  
  54. BOOL APIENTRY        DllMain _ANSI_ARGS_((HINSTANCE hInst,
  55.                 DWORD reason, LPVOID reserved));
  56.  
  57. /*
  58.  *----------------------------------------------------------------------
  59.  *
  60.  * DllEntryPoint --
  61.  *
  62.  *    This wrapper function is used by Borland to invoke the
  63.  *    initialization code for Tcl.  It simply calls the DllMain
  64.  *    routine.
  65.  *
  66.  * Results:
  67.  *    See DllMain.
  68.  *
  69.  * Side effects:
  70.  *    See DllMain.
  71.  *
  72.  *----------------------------------------------------------------------
  73.  */
  74.  
  75. BOOL APIENTRY
  76. DllEntryPoint(hInst, reason, reserved)
  77.     HINSTANCE hInst;        /* Library instance handle. */
  78.     DWORD reason;        /* Reason this function is being called. */
  79.     LPVOID reserved;        /* Not used. */
  80. {
  81.     return DllMain(hInst, reason, reserved);
  82. }
  83.  
  84. /*
  85.  *----------------------------------------------------------------------
  86.  *
  87.  * DllMain --
  88.  *
  89.  *    This routine is called by the VC++ C run time library init
  90.  *    code, or the DllEntryPoint routine.  It is responsible for
  91.  *    initializing various dynamically loaded libraries.
  92.  *
  93.  * Results:
  94.  *    TRUE on sucess, FALSE on failure.
  95.  *
  96.  * Side effects:
  97.  *    Establishes 32-to-16 bit thunk and initializes sockets library.
  98.  *
  99.  *----------------------------------------------------------------------
  100.  */
  101. BOOL APIENTRY
  102. DllMain(hInst, reason, reserved)
  103.     HINSTANCE hInst;        /* Library instance handle. */
  104.     DWORD reason;        /* Reason this function is being called. */
  105.     LPVOID reserved;        /* Not used. */
  106. {
  107.     OSVERSIONINFO os;
  108.  
  109.     switch (reason) {
  110.     case DLL_PROCESS_ATTACH:
  111.  
  112.     /*
  113.      * Registration of UT need to be done only once for first
  114.      * attaching process.  At that time set the tclWin32s flag
  115.      * to indicate if the DLL is executing under Win32s or not.
  116.      */
  117.  
  118.     if (tclProcessesAttached++) {
  119.         return FALSE;         /* Not the first initialization. */
  120.     }
  121.  
  122.     tclInstance = hInst;
  123.     os.dwOSVersionInfoSize = sizeof(os);
  124.     GetVersionEx(&os);
  125.     tclPlatformId = os.dwPlatformId;
  126.  
  127.     /*
  128.      * The following code stops Windows 3.x from automatically putting 
  129.      * up Sharing Violation dialogs, e.g, when someone tries to
  130.      * access a file that is locked or a drive with no disk in it.
  131.      * Tcl already returns the appropriate error to the caller, and they 
  132.      * can decide to put up their own dialog in response to that failure.  
  133.      *
  134.      * Under 95 and NT, the system doesn't automatically put up dialogs 
  135.      * when the above operations fail.
  136.      */
  137.  
  138.     if (tclPlatformId == VER_PLATFORM_WIN32s) {
  139.         SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS);
  140.     }
  141.  
  142.     return TRUE;
  143.  
  144.     case DLL_PROCESS_DETACH:
  145.  
  146.     tclProcessesAttached--;
  147.     if (tclProcessesAttached == 0) {
  148.  
  149.         /*
  150.          * Unregister the Tcl thunk.
  151.          */
  152.  
  153.         if (UTUnRegister != NULL) {
  154.         UTUnRegister(hInst);
  155.         }
  156.  
  157.         /*
  158.          * Cleanup any dynamically loaded libraries.
  159.          */
  160.  
  161.         UnloadLibraries();
  162.  
  163.             /*
  164.              * And finally finalize our use of Tcl.
  165.              */
  166.  
  167.             Tcl_Finalize();
  168.     }
  169.     break;
  170.     }
  171.  
  172.     return TRUE; 
  173. }
  174.  
  175. /*
  176.  *----------------------------------------------------------------------
  177.  *
  178.  * TclWinLoadLibrary --
  179.  *
  180.  *    This function is a wrapper for the system LoadLibrary.  It is
  181.  *    responsible for adding library handles to the library list so
  182.  *    the libraries can be freed when tcl.dll is unloaded.
  183.  *
  184.  * Results:
  185.  *    Returns the handle of the newly loaded library, or NULL on
  186.  *    failure.
  187.  *
  188.  * Side effects:
  189.  *    Loads the specified library into the process.
  190.  *
  191.  *----------------------------------------------------------------------
  192.  */
  193.  
  194. HINSTANCE
  195. TclWinLoadLibrary(name)
  196.     char *name;            /* Library file to load. */
  197. {
  198.     HINSTANCE handle;
  199.     LibraryList *ptr;
  200.  
  201.     handle = LoadLibrary(name);
  202.     if (handle != NULL) {
  203.     ptr = (LibraryList*) ckalloc(sizeof(LibraryList));
  204.     ptr->handle = handle;
  205.     ptr->nextPtr = libraryList;
  206.     libraryList = ptr;
  207.     } else {
  208.     TclWinConvertError(GetLastError());
  209.     }
  210.     return handle;
  211. }
  212.  
  213. /*
  214.  *----------------------------------------------------------------------
  215.  *
  216.  * UnloadLibraries --
  217.  *
  218.  *    Frees any dynamically allocated libraries loaded by Tcl.
  219.  *
  220.  * Results:
  221.  *    None.
  222.  *
  223.  * Side effects:
  224.  *    Frees the libraries on the library list as well as the list.
  225.  *
  226.  *----------------------------------------------------------------------
  227.  */
  228.  
  229. static void
  230. UnloadLibraries()
  231. {
  232.     LibraryList *ptr;
  233.  
  234.     while (libraryList != NULL) {
  235.     FreeLibrary(libraryList->handle);
  236.     ptr = libraryList->nextPtr;
  237.     ckfree((char*)libraryList);
  238.     libraryList = ptr;
  239.     }
  240. }
  241.  
  242. /*
  243.  *----------------------------------------------------------------------
  244.  *
  245.  * TclWinSynchSpawn --
  246.  *
  247.  *    32-bit entry point to the 16-bit SynchSpawn code.
  248.  *
  249.  * Results:
  250.  *    1 on success, 0 on failure.
  251.  *
  252.  * Side effects:
  253.  *    Spawns a command and waits for it to complete.
  254.  *
  255.  *----------------------------------------------------------------------
  256.  */
  257. int 
  258. TclWinSynchSpawn(void *args, int type, void **trans, Tcl_Pid *pidPtr)
  259. {
  260.     static UT32PROC UTProc = NULL;
  261.     static int utErrorCode;
  262.  
  263.     if (UTUnRegister == NULL) {
  264.     /*
  265.      * Load the Universal Thunking routines from kernel32.dll.
  266.      */
  267.  
  268.     HINSTANCE hKernel;
  269.     PUTREGISTER UTRegister;
  270.     char buffer[] = "TCL16xx.DLL";
  271.  
  272.     hKernel = TclWinLoadLibrary("Kernel32.Dll");
  273.     if (hKernel == NULL) {
  274.         return 0;
  275.     }
  276.  
  277.     UTRegister = (PUTREGISTER) GetProcAddress(hKernel, "UTRegister");
  278.     UTUnRegister = (PUTUNREGISTER) GetProcAddress(hKernel, "UTUnRegister");
  279.     if (!UTRegister || !UTUnRegister) {
  280.         UnloadLibraries();
  281.         return 0;
  282.     }
  283.  
  284.     /*
  285.      * Construct the complete name of tcl16xx.dll.
  286.      */
  287.  
  288.     buffer[5] = '0' + TCL_MAJOR_VERSION;
  289.     buffer[6] = '0' + TCL_MINOR_VERSION;
  290.  
  291.     /*
  292.      * Register the Tcl thunk.
  293.      */
  294.  
  295.     if (UTRegister(tclInstance, buffer, NULL, "UTProc", &UTProc, NULL,
  296.         NULL) == FALSE) {
  297.         utErrorCode = GetLastError();
  298.     }
  299.     }
  300.  
  301.     if (UTProc == NULL) {
  302.     /*
  303.      * The 16-bit thunking DLL wasn't found.  Return error code that
  304.      * indicates this problem.
  305.      */
  306.  
  307.     SetLastError(utErrorCode);
  308.     return 0;
  309.     }
  310.  
  311.     UTProc(args, type, trans);
  312.     *pidPtr = 0;
  313.     return 1;
  314. }
  315.  
  316. /*
  317.  *----------------------------------------------------------------------
  318.  *
  319.  * TclWinGetTclInstance --
  320.  *
  321.  *    Retrieves the global library instance handle.
  322.  *
  323.  * Results:
  324.  *    Returns the global library instance handle.
  325.  *
  326.  * Side effects:
  327.  *    None.
  328.  *
  329.  *----------------------------------------------------------------------
  330.  */
  331.  
  332. HINSTANCE
  333. TclWinGetTclInstance()
  334. {
  335.     return tclInstance;
  336. }
  337.  
  338. /*
  339.  *----------------------------------------------------------------------
  340.  *
  341.  * TclWinGetPlatformId --
  342.  *
  343.  *    Determines whether running under NT, 95, or Win32s, to allow 
  344.  *    runtime conditional code.
  345.  *
  346.  * Results:
  347.  *    The return value is one of:
  348.  *        VER_PLATFORM_WIN32s        Win32s on Windows 3.1. 
  349.  *        VER_PLATFORM_WIN32_WINDOWS    Win32 on Windows 95.
  350.  *        VER_PLATFORM_WIN32_NT    Win32 on Windows NT
  351.  *
  352.  * Side effects:
  353.  *    None.
  354.  *
  355.  *----------------------------------------------------------------------
  356.  */
  357.  
  358. int        
  359. TclWinGetPlatformId()
  360. {
  361.     return tclPlatformId;
  362. }
  363.